<?php

namespace app\common\services;

use app\common\repositories\system\PayLogRepository;
use app\common\repositories\users\UsersOauthRepository;

class PayService
{
    /**
     * 回调处理
     * @param $payLogInfo
     * @param $responseData
     * @return array|mixed
     * @throws \api\pay\exception\PayException
     */
    public static function notifyHandle($payLogInfo, $responseData)
    {
        $config = self::getPayConfig($payLogInfo);
        $wechat = new \api\pay\Pay($payLogInfo['pay_type'], $config);

        $notifyData = $wechat->notifyVerify($responseData);

        return $notifyData;
    }

    private static function getPayConfig($payLogInfo, $clientType = '')
    {
        $itemsId = $payLogInfo['items_id'];
        $payType = $payLogInfo['pay_type'];
        $domain = web_config($itemsId, 'site.site_url');
        if ($payType == 'wechat') {
            $config = web_config($itemsId, 'pay.wechat');

            $wechatConfig = web_config($itemsId, 'program.wechat');
            if ($clientType == 'app') {
                $wechatAppId = $wechatConfig['app']['app_id'] ?? '';
            } elseif ($clientType == 'mini') {
                $wechatAppId = $wechatConfig['mini']['app_id'] ?? '';
            } else {
                if (!empty($wechatConfig['mini']['app_id'])) {
                    $wechatAppId = $wechatConfig['mini']['app_id'];
                } elseif (!empty($wechatConfig['app']['app_id'])) {
                    $wechatAppId = $wechatConfig['app']['app_id'];
                } else {
                    $wechatAppId = $wechatConfig['gzh']['app_id'] ?? '';
                }
            }
            $config['mch_mode'] = 1;
            $config['app_id'] = $wechatAppId;
        }
        $config['notify_url'] = $domain . '/pay/payNotify/' . $payLogInfo['id'];
        $config['return_url'] = $domain . '/pay/payReturn/' . $payLogInfo['id'];
        return $config;
    }

    /**
     * 根据支付日志id创建支付
     *
     * @param int $payLogInfo 支付信息
     * @return false|array
     * @throws \api\pay\exception\PayException
     */
    public static function jsPayByPayLogId(int $payLogId, string $openId = '')
    {
        /** @var PayLogRepository $payLogRepository */
        $payLogRepository = app()->make(PayLogRepository::class);
        $payLogInfo = $payLogRepository->get($payLogId);
        if ($payLogInfo) {
            if ($payLogInfo['pay_type'] == 'wechat') {
                /** @var UsersOauthRepository $oauthRepository */
                $oauthRepository = app()->make(UsersOauthRepository::class);
                $openId = $openId ?: $oauthRepository->getUserOpenId($payLogInfo['user_id'], OauthService::TYPE_WECHAT_MINI);

                $config = self::getPayConfig($payLogInfo, 'mini');
                $pay = new \api\pay\Pay($payLogInfo['pay_type'], $config);
                return $pay->jsPay($openId, [
                    'subject' => $payLogInfo['remark'],
                    'order_sn' => $payLogInfo['order_sn'],
                    'amount' => $payLogInfo['amount']
                ]);
            }
            return false;
        }
        return false;
    }

    /**
     * 根据支付日志id创建支付 扫码支付
     *
     * @param array $payLogInfo 支付信息
     * @return false|array
     * @throws \api\pay\exception\PayException
     */
    public static function qrcodePayByPayLogInfo($payLogInfo)
    {
        if ($payLogInfo) {
            if ($payLogInfo['pay_type'] == 'wechat') {
                $config = self::getPayConfig($payLogInfo, 'pc');
                $pay = new \api\pay\Pay($payLogInfo['pay_type'], $config);
                $res = $pay->qrcodePay([
                    'subject' => $payLogInfo['remark'],
                    'order_sn' => $payLogInfo['order_sn'],
                    'amount' => $payLogInfo['amount']
                ]);
                if ($res && $res['return_code'] == 'SUCCESS') {
                    $domain = web_config($payLogInfo['items_id'], 'site.site_url');
                    return ['code_url' => $domain . '/qrcode/get?text=' . $res['code_url']];
                }

                return false;
            }
            return false;
        }
        return false;
    }

    /**
     * 根据支付日志id创建支付 app支付
     *
     * @param array $payLogInfo 支付信息
     * @return false|array
     * @throws \api\pay\exception\PayException
     */
    public static function appPayByPayLogInfo($payLogInfo)
    {
        if ($payLogInfo) {
            if ($payLogInfo['pay_type'] == 'wechat') {
                $config = self::getPayConfig($payLogInfo, 'app');
                $pay = new \api\pay\Pay($payLogInfo['pay_type'], $config);
                return $pay->appPay([
                    'subject' => $payLogInfo['remark'],
                    'order_sn' => $payLogInfo['order_sn'],
                    'amount' => $payLogInfo['amount']
                ]);
            }
            return false;
        }
        return false;
    }

    /**
     * 根据支付日志id创建手机支付信息
     *
     * @param int $payLogId 支付id
     * @return array|false|string
     * @throws \api\pay\exception\PayException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function wapPayByPayLogId($payLogId)
    {
        /** @var PayLogRepository $payLogRepository */
        $payLogRepository = app()->make(PayLogRepository::class);
        $payLogInfo = $payLogRepository->get($payLogId);
        if ($payLogInfo) {
            try {
                $config = self::getPayConfig($payLogInfo);
                $pay = new \api\pay\Pay($payLogInfo['pay_type'], $config);
                $res = $pay->wapPay([
                    'subject' => $payLogInfo['remark'],
                    'order_sn' => $payLogInfo['order_sn'],
                    'amount' => $payLogInfo['amount']
                ]);

                return $res;
            } catch (\Exception $e) {
                exception_log('支付订单生成失败', $e, false);
                return "订单生成失败";
            }
        }
        return false;
    }

    /**
     * 关闭订单
     *
     * @param $payLogInfo
     * @return array|\EasyWeChat\Kernel\Support\Collection|false|object|\Psr\Http\Message\ResponseInterface|string|void
     * @throws \api\pay\exception\PayException
     */
    public static function closeOrderByLogInfo($payLogInfo)
    {
        $config = self::getPayConfig($payLogInfo);
        $pay = new \api\pay\Pay($payLogInfo['pay_type'], $config);
        return $pay->closeOrder($payLogInfo['order_sn']);

        return false;

    }

    /**
     * 订单退款
     *
     * @param $payLogInfo
     * @param $refundNo
     * @param $refundDesc
     * @param $amount
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string|void
     * @throws \api\pay\exception\PayException
     */
    public static function refundByLogInfo($payLogInfo, $refundNo, $refundDesc = '', $amount = 0)
    {
        $config = self::getPayConfig($payLogInfo);
        $amount = min($amount, $payLogInfo['amount']);
        $pay = new \api\pay\Pay($payLogInfo['pay_type'], $config);
        $res = $pay->refundByTransactionId($payLogInfo['transaction_id'], $refundNo, $payLogInfo['amount'], $amount, $refundDesc);
        if ($payLogInfo['pay_type'] == 'wechat') {
            if ($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') {
                return [
                    'status' => 0
                ];
            } else {
                return [
                    'status' => -1,
                    'err_msg' => ($res['return_msg'] ?? '') . ' ' . ($res['err_code_des'] ?? '')
                ];
            }
        }
    }

}